package net.sudot.chess.listener;

import com.fasterxml.jackson.databind.JsonNode;
import net.sudot.chess.business.dto.ReflectFieldDTO;
import net.sudot.chess.business.model.SystemConfig;
import net.sudot.chess.business.model.enums.SystemConfigType;
import net.sudot.chess.business.service.SystemConfigService;
import net.sudot.chess.config.SystemProperties;
import net.sudot.commons.json.JsonUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 系统启动完成监听事件
 *
 * @author tangjialin on 2018-04-17.
 */
@Component
public class SystemStartupCompleteListener implements ApplicationListener<ContextRefreshedEvent> {
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private SystemProperties systemProperties;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent refreshedEvent) {
        ApplicationContext applicationContext = refreshedEvent.getApplicationContext();
        if (applicationContext.getParent() != null) { return; }
        Map<String, Object> allPropertiesMap = new HashMap<>();
        // 使用此方法可以避免枚举类有复杂定义导致无限递归
        JsonNode jsonNode = JsonUtils.toObject(JsonUtils.toJson(systemProperties), JsonNode.class);
        loadSystemProperties(jsonNode, null, allPropertiesMap);
        List<SystemConfig> systemConfigList = systemConfigService.findAll();
        Map<String, String> systemConfigKeySet = new HashMap<>(systemConfigList.size());
        for (SystemConfig systemConfig : systemConfigList) {
            Object value = allPropertiesMap.get(systemConfig.getAttributeKey());
            if (value == null) {
                systemConfigService.delete(systemConfig.getId());
            } else {
                systemConfigKeySet.put(systemConfig.getAttributeKey(), systemConfig.getAttributeValue());
            }
        }
        Iterator<Map.Entry<String, Object>> iterator = allPropertiesMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> next = iterator.next();
            String key = next.getKey();
            try {
                ReflectFieldDTO reflectFieldDTO = systemConfigService.getReflectField(key);
                Field field = reflectFieldDTO.getField();
                Class<?> fieldType = field.getType();
                SystemConfigType systemConfigType = systemConfigService.getSystemConfigType(field);
                String value = systemConfigKeySet.get(key);
                if (value != null) {
                    Object deserialize = systemConfigType.deserialize(value, fieldType);
                    reflectFieldDTO.setValue(deserialize);
                    continue;
                }
                systemConfigService.save(new SystemConfig().setAttributeKey(key).setAttributeValue(systemConfigType.serialize(next.getValue(), fieldType)).setAttributeType(systemConfigType));
            } catch (Exception e) {
                throw new RuntimeException("系统参数[" + key + "]初始化异常", e);
            }
        }
    }

    private void loadSystemProperties(JsonNode jsonNode, String parentKey, Map<String, Object> systemConfig) {
        parentKey = parentKey == null ? "" : parentKey;
        Iterator<Map.Entry<String, JsonNode>> iterator = jsonNode.fields();
        while (iterator.hasNext()) {
            Map.Entry<String, JsonNode> nodeEntry = iterator.next();
            String key = parentKey + nodeEntry.getKey();
            JsonNode value = nodeEntry.getValue();
            if (value.isObject() || value.isPojo()) {
                loadSystemProperties(value, key + ".", systemConfig);
            } else {
                systemConfig.put(key, value.asText());
            }
        }
    }
}
